home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / FileLib / FileMoveLib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-17  |  5.7 KB  |  170 lines  |  [TEXT/KAHL]

  1. /* Functions for moving files. One of the functions will automatically
  2.     use the most efficient method for moving a file: if the source and
  3.     destination are on the same volume it uses CatMove, while if they are
  4.     on different volumes the source file is copied and then deleted.
  5.     Another useful function provides a more portable (ie, system 6.0
  6.     through 7.0 compatible, and compatible with all volumes) implementation
  7.     of FSpExchangeFiles.
  8.  
  9.     93/10/14 aih
  10.     - file's catalog is copied during a file exchange in a simpler
  11.     manner than before
  12.     
  13.     93/03/19 AIH
  14.     - Went back to old way of using CatMove since the new way doesn't
  15.     work
  16.     
  17.     91/05/31 AIH
  18.     - Simplified use of CatMove as described in the latest version (February
  19.     '91) of TN226
  20.  
  21.     91/05/27 AIH
  22.     - The function for exchanging two files uses FSpExchangeFiles if possible
  23.     
  24.     91/05/23 AIH
  25.     - The function for exchanging two files is a little more robust
  26.     
  27.     91/05/17 AIH
  28.     - Fixed possible bug with A/UX and CatMove
  29.     
  30.     91/05/08 AIH
  31.     - Added function to exchange two files
  32.     
  33.     91/03/23 Ari Halberstadt (AIH)
  34.     - Fixed bug in way CatMove was called: the routine expects a Pascal string,
  35.     not a C string. */
  36.  
  37. #include <string.h>
  38. #include "MacLib.h"
  39. #include "VolumeLib.h"
  40. #include "FileLib.h"
  41.  
  42. /* Move the source file to the destination file. If the source and destination
  43.     are on the same volume then the file isn't actually moved, instead the 
  44.     catalog entries are changed by calling CatMove (see TN226). When the
  45.     source and destination are on separate volumes the source is first
  46.     copied to the destination and then the source is deleted. */
  47. void FileMove(FileType *src, FileType *dst)
  48. {
  49.     Boolean samevol = false; /* true if the files are on the same volume */
  50.     FileNameType name;
  51.     OSErr err = noErr;
  52.     
  53.     require(FileValid(src));
  54.     require(FileValid(dst));
  55.     /* check for existing destination */
  56.     if (FileExists(dst))
  57.         FailOSErr(dupFNErr);
  58.     /* use a more efficient way of moving the files if they're on the same
  59.         volume */
  60.     samevol = (src->vol == dst->vol);
  61.     if (samevol) {
  62.         err = CatMove(src->vol, src->dir, src->pnm, dst->dir, NULL);
  63.         if (err == badMovErr) {
  64.             /* we're probably on A/UX and it's mapping the volumes so
  65.                 that two physically different volumes still have the
  66.                 same vRefNum (see TN229) */
  67.             samevol = false;
  68.             err = noErr;
  69.         }
  70.         else {
  71.             /* CatMove keeps the name of the original file, so we rename it
  72.                 to use the name of the destination */
  73.             FailOSErr(err);
  74.             strcpy(name, FileName(dst));
  75.             FileNameSet(dst, src->cnm);
  76.             FileRename(dst, name);
  77.         }
  78.     }
  79.     /* if the files aren't on the same volume, copy the source file
  80.         to the destination file and then delete the source file */
  81.     if (! samevol) {
  82.         FileCopy(src, dst);
  83.         FileDelete(src);
  84.     }
  85. }
  86.  
  87. /* Under system 7.0 the routine FSpExchangeFiles can be used with certain
  88.     volumes to swap two files when doing a "safe save". To use the routine
  89.     FSpExchangeFiles, the system software must support it, the volume
  90.     containing the files must support it, and both files must be on the same
  91.     volume. If any of these conditions is not met then other File Manager
  92.     routines are used. Unlike the real FspExchangeFiles, both files must be
  93.     closed for this function to work in all cases, since I can't modify the
  94.     File Control Blocks of open files.
  95.     
  96.     In this implementation, the file 'fp1' replaces the file 'fp2'.
  97.     If this function terminates successfully, then the file 'fp1' no longer
  98.     exists, and the old version of the file 'fp2' is discarded. Every effort
  99.     has been made to ensure that the old version of the file 'fp2' is not
  100.     discarded until the file 'fp1' has successfully replaced it.
  101.     All the Finder information of the original file 'fp2', including the
  102.     creation date, is preserved. For greatest efficiency--to avoid having
  103.     to copy the file, instead of moving it by swapping catalog entries, and
  104.     to take advantage of FSpExchangeFiles--'fp1' and 'fp2' should be on
  105.     the same volume, though the function will work even if the files are on
  106.     different volumes.
  107.     
  108.     Unlike the routine FSpExchangeFiles, only the file 'fp1' remains,
  109.     except it is now in the location indicated by 'fp2'. This is
  110.     equivalent to a call to FSpExchangeFiles followed by a call to
  111.     delete the file 'fp1'. In fact, this is exactly what this
  112.     function attempts to do. */
  113. void FileExchange(FileType *fp1, FileType *fp2)
  114. {
  115.     CInfoPBRec            cat;        /* catalog entry for fp1 */
  116.     FileNameType        name;        /* unique name for fp2 */
  117.     FSSpec                spec1;    /* spec for fp1 */
  118.     FSSpec                spec2;    /* spec for fp2 */
  119.     volatile FileType    oldfp2;    /* renamed fp2 (ie, old version) */
  120.     volatile Boolean    renamed = false;
  121.     volatile Boolean    moved = false;
  122.     
  123.     require(FileExists(fp1));
  124.     require(FileExists(fp2));
  125.     require(fp1->ref == FILE_CLOSED);
  126.     require(fp2->ref == FILE_CLOSED);
  127.  
  128.     TRY {
  129.         /* use FSpExchangeFiles if possible */
  130.         if (fp1->vol == fp2->vol && VolumeSupportsFSpExchangeFiles(fp1->vol)) {
  131.             FileToFSSpec(fp1, &spec1);
  132.             FileToFSSpec(fp2, &spec2);
  133.             FailOSErr(FSpExchangeFiles(&spec1, &spec2));
  134.             FileDelete(fp1);
  135.         }
  136.         else {
  137.         
  138.             /* remember catalog info */
  139.             FileCatalog(fp2, &cat);
  140.     
  141.             /* move fp2 out of the way by giving it a unique name */
  142.             strcpy(name, FileName(fp2));
  143.             FileUniqueInList(name, fp1, fp2, NULL);
  144.             FileClone(fp2, &oldfp2);
  145.             FileRename(&oldfp2, name);
  146.             renamed = true;
  147.  
  148.             /* move fp1 into the old location of fp2 */
  149.             FileMove(fp1, fp2);
  150.             moved = true;
  151.             
  152.             /* copy catalog info, but use current time as modification time */
  153.             GetDateTime(&cat.hFileInfo.ioFlMdDat);
  154.             FileCatalogSet(fp2, &cat);
  155.  
  156.             /* everything was successful, so remove old copy of fp2 */
  157.             FileDelete(&oldfp2);
  158.                                             
  159.             ensure(! FileExists(fp1));
  160.             ensure(FileExists(fp2));
  161.         }
  162.     } CATCH {
  163.         if (moved)
  164.             FileMove(fp2, fp1);
  165.         if (renamed)
  166.             FileRename(&oldfp2, FileName(fp2));
  167.     } ENDTRY;
  168. }
  169.  
  170.